import { useState } from "react";
import { useReactive, useUpdateEffect } from "ahooks";
import useFetch, { UseFetchOptions } from "./useFetch";

type Pages = {
  page: number;
  pageSize;
};

type UseListOptions<TData, TParams extends any[]> = {
  page?: number;
  pageSize?: number;
  defaultParams?: TParams;
} & Omit<UseFetchOptions<TData, [Pages, ...TParams]>, "defaultParams">;

export default function useList<TData = unknown, TParams extends any[] = any[]>(
  url: string | ((params: [Pages, ...TParams]) => string),
  options?: UseListOptions<{ total: number; list: TData[] }, TParams>
) {
  const {
    page = 1,
    pageSize = 30,
    defaultParams = [],
    ...restOptions
  } = options || {};

  const pages = useReactive<Pages>({ page, pageSize });

  const [total, setTotal] = useState(0);
  const [isAll, setIsAll] = useState(false);
  const [list, setList] = useState<TData[]>([]);

  const { data, run, params, mutate, ...rest } = useFetch<
    {
      total: number;
      list: TData[];
    },
    [Pages, ...TParams]
  >(url, "GET", {
    ...restOptions,
    defaultParams: [pages, ...defaultParams] as [Pages, ...TParams],
  });

  useUpdateEffect(() => {
    if (data) {
      const newList =
        pages.page === 1 ? data.list || [] : [...list, ...data.list];

      setTotal(data.total);
      setIsAll(newList.length >= (data.total || data.list?.length || 0));
      setList(newList);
    }
  }, [data]);

  const nextPage = () => {
    if (isAll) return;
    pages.page += 1;
    // @ts-expect-error
    run(pages, params[1]);
  };

  const cusMutate = () => mutate({ list: [], total: 0 });
  const execute = (...parmas: any[]) => run.call(null, pages, ...parmas);

  const resetToFirst = (params?) => {
    cusMutate();
    pages.page = 1;
    execute(params);
  };

  return {
    ...rest,

    list,
    total,
    params,
    originData: data,
    mutate: cusMutate,
    run: execute,
    resetToFirst,
    nextPage,
  };
}
